﻿/***************************************************
//  Copyright (c) Premium Tax Free 2011
***************************************************/

using System;
using System.Collections;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using PremierTaxFree.PTFLib.Data;
using PremierTaxFree.PTFLib.Threading;

namespace PremierTaxFree.PTFLib.Net
{
    public class UserAuth : IBinaryReadable
    {
        public string Name { get; set; }
        public string Password { get; set; }

        public void Read(BinaryReader reader)
        {
            Name = reader.ReadString();
            Password = reader.ReadString();
        }
    }

    public class DataEventArgs<T> : EventArgs where T : IBinaryReadable
    {
        public T Data { get; private set; }
        public DataEventArgs(T t)
        {
            Data = t;
        }
    }

    public class PipeServer<T> : ThreadWorkerBase where T : IBinaryReadable, new()
    {
        private readonly string m_ServerName;

        public event EventHandler<DataEventArgs<T>> Data;

        public PipeServer(string serverName)
        {
            m_ServerName = serverName;
        }

        protected override void ThreadFunction(object data)
        {
            using (NamedPipeServerStream pipeStream = new NamedPipeServerStream(m_ServerName))
            {
                pipeStream.WaitForConnection();

                using (BinaryReader reader = new BinaryReader(pipeStream))
                {
                    while (pipeStream.IsConnected)
                    {
                        T t = new T();
                        t.Read(reader);
                        if (Data != null)
                            Data(this, new DataEventArgs<T>(t));
                    }
                }
            }
        }
    }

    public class PipeClient : ThreadWorkerBase
    {
        private readonly Queue m_DataQueue = Queue.Synchronized(new Queue());
        private readonly string m_ServerName;

        public PipeClient(string serverName)
        {
            m_ServerName = serverName;
        }

        protected override void ThreadFunction(object data)
        {
            // Ensure that we only start the client after the server has created the pipe
            ManualResetEvent SyncClientServer = (ManualResetEvent)data;

            // Only continue after the server was created -- otherwise we just fail badly
            SyncClientServer.WaitOne();

            using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(m_ServerName))
            {
                // The connect function will indefinately wait for the pipe to become available
                // If that is not acceptable specify a maximum waiting time (in ms)
                pipeStream.Connect();

                //Console.WriteLine("[Client] Pipe connection established");
                using (StreamWriter sw = new StreamWriter(pipeStream))
                {
                    sw.AutoFlush = true;
                    string temp;
                    //Console.WriteLine("Please type a message and press [Enter], or type 'quit' to exit the program");
                    while ((temp = Console.ReadLine()) != null)
                    {
                        if (temp == "quit") break;
                        sw.WriteLine(temp);
                    }
                }
            }
        }

        //static void Main(string[] args)
        //{

        //    // To simplify debugging we are going to create just one process, and have two tasks
        //    // talk to each other. (Which is a bit like me sending an e-mail to my co-workers)

        //    ProgramPipeTest Server = new ProgramPipeTest();
        //    ProgramPipeTest Client = new ProgramPipeTest();

        //    Thread ServerThread = new Thread(Server.ThreadStartServer);
        //    Thread ClientThread = new Thread(Client.ThreadStartClient);

        //    ServerThread.Start();
        //    ClientThread.Start();
        //}
    }
}
